#pragma once

#include <vector>

using namespace std;

namespace msl {
    template<typename T>
    class Set {
    public:
        class SetIterator {
        public:
            using iterator_category = std::bidirectional_iterator_tag;
            using difference_type = std::ptrdiff_t;
            using value_type = T;
            using pointer = T*;
            using reference = T&;

            friend Set<T>::SetIterator Set<T>::begin();
            friend Set<T>::SetIterator Set<T>::end();
            friend Set<T>::SetIterator Set<T>::insert(T value);

            template <typename t>
            friend int leaf_count(Set<t>&);

        private:
            int el_ind;
            Set* p;

        private:
            T* getptrSetElement() const;

        private:
            SetIterator(Set<T>* par, int ind);

        public:
            reference operator*() const;
            pointer operator->();

            SetIterator& operator++();
            SetIterator operator++(int);
            SetIterator& operator--();
            SetIterator operator--(int);

            bool operator==(const SetIterator& other);
            bool operator!=(const SetIterator& other);
        };

        template <typename t>
        friend string print_set(Set<t>&);
        template <typename t>
        friend int leaf_count(Set<t>&);

    private:
        vector<T> els;
        vector<bool> used;

    public:
        Set();
        Set(const Set& other);
        Set(std::initializer_list<T> values);
        void create_balance_tree(std::vector<T> vals);
        ~Set();
        void copy(const Set& other);

        Set operator=(const Set& other);

    private:
        bool exist(int ind);

    public:
        SetIterator begin();
        SetIterator end();

        bool empty() const;
        void clear();
        SetIterator insert(T value);
        void erase(SetIterator it);
    };

    template <typename T>
    string print_set(Set<T>&);
    template <typename T>
    int leaf_count(Set<T>&);

};


#include "set.hpp"
